package com.ruoyi.web.sso.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.Ztree;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.web.sso.common.util.*;
import com.ruoyi.web.sso.domain.*;
import com.ruoyi.web.sso.domain.DTO.PlatformMenuDTO;
import com.ruoyi.web.sso.domain.DTO.RoleDTO;
import com.ruoyi.web.sso.domain.vo.AddMenu;
import com.ruoyi.web.sso.domain.vo.SimpleMenuList;
import com.ruoyi.web.sso.domain.vo.StaffDetails;
import com.ruoyi.web.sso.domain.vo.ZtreeSso;
import com.ruoyi.web.sso.mapper.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.ruoyi.web.sso.service.IMenuService;
import com.ruoyi.common.core.text.Convert;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;

/**
 * 菜单权限Service业务层处理
 * 
 * @author ruoyi
 * @date 2021-10-28
 */
@Service
public class MenuServiceImpl implements IMenuService 
{
    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private PlatformMapper platformMapper;
    @Autowired
    private RoleMenuMapper roleMenuMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private StaffMapper staffMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private StaffRoleMapper staffRoleMapper;

    /**
     * 查询菜单权限
     * 
     * @param menuId 菜单权限主键
     * @return 菜单权限
     */
    @Override
    public Menu selectMenuByMenuId(String menuId)
    {
        return menuMapper.selectMenuByMenuId(menuId);
    }

    /**
     * 查询菜单权限列表
     * 
     * @param menu 菜单权限
     * @return 菜单权限
     */
    @Override
    public List<Menu> selectMenuList(Menu menu)
    {
        return menuMapper.selectMenuList(menu);
    }

    /**
     * 新增菜单权限
     * 
     * @param menu 菜单权限
     * @return 结果
     */
    @Override
    public int insertMenu(Menu menu)
    {
        menu.setCreateTime(DateUtils.getNowDate());
        return menuMapper.insertMenu(menu);
    }

    /**
     * 修改菜单权限
     * 
     * @param menu 菜单权限
     * @return 结果
     */
    @Override
    public int updateMenu(Menu menu)
    {
        Menu menu1 = menuMapper.selectMenuByMenuId(menu.getMenuId());
        if (AssertUtil.isEmpty(menu1)){
            return  0;
        }
        menu.setUpdateTime(DateUtils.getNowDate());
        return menuMapper.updateMenu(menu);
    }

    /**
     * 批量删除菜单权限
     * 
     * @param menuIds 需要删除的菜单权限主键
     * @return 结果
     */
    @Override
    public int deleteMenuByMenuIds(String menuIds)
    {
        return menuMapper.deleteMenuByMenuIds(Convert.toStrArray(menuIds));
    }

    /**
     * 删除菜单权限信息
     * 
     * @param menuId 菜单权限主键
     * @return 结果
     */
    @Override
    public int deleteMenuByMenuId(String menuId)
    {
        return menuMapper.deleteMenuByMenuId(menuId);
    }




    @Override
    public AjaxResult add(AddMenu addMenu) {
        if (StringUtils.equals(addMenu.getPlatformId(),"")){
            return AjaxResult.error("系统ID不能为空");
        }
        Platform platform  = platformMapper.selectPlatformByPlatformId(addMenu.getPlatformId());
        if (AssertUtil.isEmpty(platform)){
            return AjaxResult.error("系统ID不存在！");
        }
        if (StringUtils.equals(addMenu.getParentId(),"")){
            addMenu.setParentId("0");
        }
        Menu menu = new Menu();
        BeanUtils.copyProperties(addMenu , menu);
        menu.setMenuId(UuidUtil.getUuid());
        menuMapper.insertMenu(menu);
        return AjaxResult.success("添加成功");
    }

    @Override
    public AjaxResult addRoleMenu(RoleMenu roleMenu) {
         Menu menu =menuMapper.selectMenuByMenuId(roleMenu.getMenuId());
        if (AssertUtil.isEmpty(menu)){
            return AjaxResult.error("菜单ID不存在！");
        }
        Role role =roleMapper.selectRoleByRoleId(roleMenu.getRoleId());
        if (AssertUtil.isEmpty(role)){
            return AjaxResult.error("角色ID不存在！");
        }
        RoleMenu sosRoleMenu1 = roleMenuMapper.selectIsExistence(roleMenu);
        if (AssertUtil.isEmpty(sosRoleMenu1)){
            roleMenuMapper.insertRoleMenu(roleMenu);
            //更新redis角色信息
            //setRedisRoleMenu(roleMenu.getRoleId());
            return AjaxResult.success( "添加成功");
        }else {
            return AjaxResult.error( "已存在数据");
        }
    }

    @Override
    public AjaxResult selectRoleMenu(HttpServletRequest request, String platformId, String roleId) {
        String headerNames = request.getHeader("Authorization");
        if (AssertUtil.isEmpty(headerNames)){
            return  AjaxResult.error("请求参数错误！");
        }
        Platform platform  = platformMapper.selectPlatformByPlatformId(platformId);
        if (AssertUtil.isEmpty(platform)){
            return AjaxResult.error("系统ID不存在！");
        }
        StaffDetails staffDetails =(StaffDetails)redisTemplate.opsForValue().get(headerNames);
        return AjaxResult.success(selectMenusByStaffId(staffDetails.getId(),platformId,roleId));
    }

    public List<Menu> selectMenusByStaffId(String staffId, String platformId, String roleId){
        Map<String,Object> map = new HashMap<>();
        map.put("staffId",staffId);
        map.put("platformId",platformId);
        map.put("roleId",roleId);
        return menuMapper.selectMenusByStaffId(map);
    }

    @Override
    public List<SimpleMenuList> selectSimpleMenuList(String staffId, String platformId) {
        Map<String,Object> map = new HashMap<>();
        map.put("staffId",staffId);
        map.put("platformId",platformId);
        return menuMapper.selectSimpleMenuList(map);
    }

    @Override
    public List<SimpleMenuList> selectSimpleMenuList(String staffId, String platformId, String val) {
        Map<String,Object> map = new HashMap<>();
        map.put("staffId",staffId);
        map.put("platformId",platformId);
        return getChildPerms(menuMapper.selectSimpleMenuList(map),"0");
    }

    /**
     * 根据父节点的ID获取所有子节点
     *
     * @param list 分类表
     * @param parentId 传入的父节点ID
     * @return String
     */
    public List<SimpleMenuList> getChildPerms(List<SimpleMenuList> list, String parentId)
    {
        List<SimpleMenuList> returnList = new ArrayList<SimpleMenuList>();
        for (Iterator<SimpleMenuList> iterator = list.iterator(); iterator.hasNext();)
        {
            SimpleMenuList t = (SimpleMenuList) iterator.next();
            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (StringUtils.equals(t.getParentId(),parentId) )
            {
                recursionFn(list, t);
                returnList.add(t);
            }
        }
        return returnList;
    }

    /**
     * 递归列表
     *
     * @param list
     * @param t
     */
    private void recursionFn(List<SimpleMenuList> list, SimpleMenuList t)
    {
        // 得到子节点列表
        List<SimpleMenuList> childList = getChildList(list, t);
        t.setChildList(childList);
        for (SimpleMenuList tChild : childList)
        {
            if (hasChild(list, tChild))
            {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SimpleMenuList> getChildList(List<SimpleMenuList> list, SimpleMenuList t)
    {
        List<SimpleMenuList> tlist = new ArrayList<SimpleMenuList>();
        Iterator<SimpleMenuList> it = list.iterator();
        while (it.hasNext())
        {
            SimpleMenuList n = (SimpleMenuList) it.next();
            if (StringUtils.equals(n.getParentId() ,t.getMenuId()))
            {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SimpleMenuList> list, SimpleMenuList t)
    {
        return getChildList(list, t).size() > 0 ? true : false;
    }

    /**
     * 根据角色ID查询菜单
     *
     * @return 菜单列表
     */
    @Override
    public List<ZtreeSso> roleMenuTreeData(String roleId, String platformId)
    {
        List<ZtreeSso> ztrees = new ArrayList<ZtreeSso>();

        List<Menu> menuList = selectMenusByStaffId(null,platformId,null);
        if (AssertUtil.isNotEmpty(roleId))
        {
            Map<String,Object> map = new HashMap<>();
            map.put("roleId",roleId);
            List<String> roleMenuList = menuMapper.selectMenuTree(map);
            ztrees = initZtree(menuList, roleMenuList, true);
        }
        else
        {
            ztrees = initZtree(menuList, null, true);
        }
        return ztrees;
    }



    /**
     * 对象转菜单树
     *
     * @param menuList 菜单列表
     * @param roleMenuList 角色已存在菜单列表
     * @param permsFlag 是否需要显示权限标识
     * @return 树结构列表
     */
    public List<ZtreeSso> initZtree(List<Menu> menuList, List<String> roleMenuList, boolean permsFlag)
    {
        List<ZtreeSso> ztrees = new ArrayList<ZtreeSso>();
        boolean isCheck = AssertUtil.isNotEmpty(roleMenuList);
        for (Menu menu : menuList)
        {
            ZtreeSso ztree = new ZtreeSso();
            ztree.setId(menu.getMenuId());
            ztree.setpId(menu.getParentId());
            ztree.setName(transMenuName(menu, permsFlag));
            ztree.setTitle(menu.getMenuName());
            if (isCheck)
            {
                ztree.setChecked(roleMenuList.contains(menu.getMenuId() + menu.getPerms()));
            }
            ztrees.add(ztree);
        }
        return ztrees;
    }
    public String transMenuName(Menu menu, boolean permsFlag)
    {
        StringBuffer sb = new StringBuffer();
        sb.append(menu.getMenuName());
//        if (permsFlag)
//        {
//            if (AssertUtil.isNotEmpty(menu.getPerms())){
//                sb.append("<font color=\'#888\'>&nbsp;&nbsp;&nbsp;" + menu.getPerms() + "</font>");
//            }
//        }
        return sb.toString();
    }

    @Override
    public AjaxResult deleteMenuById(String menuId) {

        if (menuMapper.selectCountMenuByParentId(menuId) > 0)
        {
            return AjaxResult.warn("存在子菜单,不允许删除");
        }
        if (roleMenuMapper.selectCountRoleMenuByMenuId(menuId) > 0)
        {
            return AjaxResult.warn("菜单已分配,不允许删除");
        }
        if (AssertUtil.isEmpty(menuMapper.selectMenuByMenuId(menuId))){
            return AjaxResult.error("ID不存在");
        }
        menuMapper.deleteMenuByMenuId(menuId);
        return AjaxResult.success("删除成功");
    }


    @Override
    public boolean isMenu(String staffId, String platformId,String url) {

        List<SimpleMenuList>  list = selectSimpleMenuList(staffId,platformId);
        if (list.size() ==0  || AssertUtil.isEmpty(list)){
            throw new BusinessException(ErrorCode.SESSION_TOKEN_ERROR, "SessionToken异常！！");
        }
        for (int i = 0; i < list.size(); i++) {
            if (StringUtils.equals( list.get(i).getUrl() , url)) {
                return true;
            }
        }
        throw new BusinessException(ErrorCode.SESSION_TOKEN_ERROR, "SessionToken异常！！");
    }

    public List<SimpleMenuList> delParentIdVisible(List<SimpleMenuList> list)
    {
        List<SimpleMenuList> returnList = new ArrayList<SimpleMenuList>();
        for (int i = 0; i <list.size() ; i++) {
            if (StringUtils.equals(list.get(i).getVisible(),"0") && isParentIdVisible(list,list.get(i).getParentId())){
                returnList.add(list.get(i));
            }
        }
        return returnList;
    }

    public boolean isParentIdVisible(List<SimpleMenuList> list,String parentId)
    {
        if (StringUtils.equals(parentId,"0")){
            return true;
        }
        for (int i = 0; i <list.size() ; i++) {
            if (StringUtils.equals(list.get(i).getMenuId(),parentId)){
                if ( StringUtils.equals(list.get(i).getVisible(),"1")){
                    return false;
                }else {
                    if (StringUtils.equals(list.get(i).getParentId(),"0")){
                        return true;
                    }else {
                        isParentIdVisible(list,parentId);
                    }
                }
            }
        }
        return false;
    }



    /**
     * 根据父节点的ID获取所有子节点
     *
     * @param list 分类表
     * @return String
     */
    public List<PlatformMenuDTO> getChildPerms(List<PlatformMenuDTO> list)
    {
        List<PlatformMenuDTO> returnList = new ArrayList<PlatformMenuDTO>();
        for (Iterator<PlatformMenuDTO> iterator = list.iterator(); iterator.hasNext();)
        {
            PlatformMenuDTO t = (PlatformMenuDTO) iterator.next();
            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (StringUtils.equals(t.getParentId(),"0"))
            {
                recursionFn(list, t);
                returnList.add(t);
            }
        }
        return returnList;
    }

    /**
     * 递归列表
     *
     * @param list
     * @param t
     */
    private void recursionFn(List<PlatformMenuDTO> list, PlatformMenuDTO t)
    {
        // 得到子节点列表
        List<PlatformMenuDTO> childList = getChildList(list, t);
        t.setNodes(childList);
        for (PlatformMenuDTO tChild : childList)
        {
            if (hasChild(list, tChild))
            {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<PlatformMenuDTO> getChildList(List<PlatformMenuDTO> list, PlatformMenuDTO t)
    {
        List<PlatformMenuDTO> tlist = new ArrayList<PlatformMenuDTO>();
        Iterator<PlatformMenuDTO> it = list.iterator();
        while (it.hasNext())
        {
            PlatformMenuDTO n = (PlatformMenuDTO) it.next();
            if (StringUtils.equals(n.getParentId(),t.getMenuId()))
            {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<PlatformMenuDTO> list, PlatformMenuDTO t)
    {
        return getChildList(list, t).size() > 0 ? true : false;
    }


    @Override
    public List<PlatformMenuDTO> getTermMenus(String platformId) {
        if (AssertUtil.isEmpty( platformMapper.selectPlatformByPlatformId(platformId))){
            throw new BusinessException(ErrorCode.SESSION_TOKEN_ERROR, "没有对应系统");
        }
        Menu menu = new Menu();
        menu.setPlatformId(platformId);
        menu.setDeleted(String.valueOf(0));
        menu.setVisible(String.valueOf(0));
        List<Menu>  menus = menuMapper.selectMenuList(menu);
        if (menus.size()>0){
            return  getPlatformMenuDTO(menus);
        }else {
            throw new BusinessException(ErrorCode.SESSION_TOKEN_ERROR, "菜单为空");
        }
    }

    @Override
    public List<Menu> roleIdAndPlatformIdByTermMenus(String platformId, String roleId) {
        if (AssertUtil.isEmpty( platformMapper.selectPlatformByPlatformId(platformId))){
            throw new BusinessException(ErrorCode.SESSION_TOKEN_ERROR, "没有对应系统");
        }
        List<Menu>  menus = menuMapper.roleIdAndPlatformIdByTermMenus(platformId,roleId);
        return menus;
    }

    public  List<PlatformMenuDTO> getPlatformMenuDTO(List<Menu>  menus){
    List<PlatformMenuDTO> platformMenuDTOList = menus.stream().map(person -> {
        PlatformMenuDTO platformMenuDTO = new PlatformMenuDTO();
        BeanUtils.copyProperties(person,platformMenuDTO);
        return platformMenuDTO; }).collect(Collectors.toList());
        return  getChildPerms(platformMenuDTOList);
    }

    @Override
    @Transactional
    public RoleDTO setRoleMenus(String roleId, String[] menuIds, String platformId) {
        Role role =  roleMapper.selectRoleByRoleId(roleId);
        if (AssertUtil.isEmpty(role)){
            throw new BusinessException(ErrorCode.STAFF_HAS_NO_ROLE, "该用户没有角色");
        }
        //删除原有的关系
        roleMenuMapper.deleteRoleMenuByRoleId(role.getRoleId(),platformId);

        for (int i = 0; i < menuIds.length; i++) {
            Menu menu = menuMapper.selectMenuByMenuId(menuIds[i]);
            if (AssertUtil.isEmpty(menu)){
                throw new BusinessException(ErrorCode.SESSION_TOKEN_ERROR, "菜单为空");
            }
            if (!StringUtils.equals(menu.getPlatformId(),platformId)){
                throw new BusinessException(ErrorCode.SESSION_TOKEN_ERROR, "没有对应系统");
            }
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setRoleId(roleId);
            roleMenu.setMenuId(menu.getMenuId());
            roleMenuMapper.insertRoleMenu(roleMenu);

            //更新redis角色信息
            //setRedisRoleMenu(roleMenu.getRoleId());
        }
        RoleDTO roleDTO = new RoleDTO();
        roleDTO.setId(role.getRoleId());
        roleDTO.setRoleCode(role.getRoleCode());
        roleDTO.setRoleName(role.getRoleName());
        return roleDTO;
    }

//    public void  setRedisRoleMenu(String roleId){
//        List<Map<String,Object>> map = staffMapper.getRoleIdAndPlatformIdByMenuList(roleId);
//        if (AssertUtil.isEmpty(map)){
//            map = new ArrayList<>();
//        }
//        redisTemplate.opsForValue().set(roleId,map);
//    }
}
